import pickle
import tkSimpleDialog as tks
import tkFileDialog as tkf
import tkMessageBox as tkm
import random
import xmlrpclib
from batiment import *
from Etoile import *
from Planete import *
from unite import *
from univers import *
from vueClient import *
from modeleClient import *
import threading

class Controleur(object):
    def __init__(self):
        self.serveur = xmlrpclib.ServerProxy('http://localhost:11502')
        self.vue = Vue(self)
        self.modele=Modele(self)
        self.compteur=0
        self.vue.root.mainloop()
 
          
    ##demande au modele de creer l'univers avec valeurs par defaut,
    ##envoie l'univers au serveur
    ##appelle joindrePartie() pour joindre la partie cree    
    def creerDefaut(self,nbEtoiles,largeur,hauteur,profondeur,nbAI):
        if self.serveur.demanderSiPartie()== "oui":
            tkm.askretrycancel("Deja une partie", "Il y a deja une partie en cours")
        else:
            univers=self.modele.creerDefaut(nbEtoiles,largeur,hauteur,profondeur)
            univers=pickle.dumps(univers)
            nbAI=pickle.dumps(nbAI)
            confirmation = self.serveur.creerUnivers(univers, nbAI)
            if confirmation == "ok":
                self.debuterPartie()
    
    
    ##demande l'objet joueur au serveur
    ##Joins la partie en cours (ou qui vient d'etre cree)
    def joindrePartie(self):
        #Verifier si il y a un serveur
        try:
            ##verfifie avec le serveur si une partie est en cours
            if self.serveur.demanderSiPartie()== "non":
                if tkm.askretrycancel("Aucune partie", "Il n'y a aucune partie en cours"):
                    self.joindrePartie()
                else:
                    self.vue.afficherEcranDepart()
            else:
                self.debuterPartie()
        #Si il n'y a pas de serveur
        except:
            if tkm.askretrycancel("Pas de serveur", "Il n'y a pas de serveur"):
                self.joindrePartie
            else:
                self.vue.afficherEcranDepart
    
    ##debute la partie qui a ete cree ou jointe
    def debuterPartie(self):
        ##chercher nom du joueur
        nick=str(self.vue.entryVotreNom.get())
        ##demande l'univers au serveur (le serveur cree l'objet Joueur et la bin du joueur
        univers=pickle.loads(self.serveur.joindrePartie(nick))
        ##demande l'objet joueur au serveur
        joueurs=pickle.loads(self.serveur.getJoueur(nick))
        joueur = joueurs[nick]
        couleurs = {}
        for i in joueurs:
            couleurs[joueurs[i].nom]=joueurs[i].couleur
        ##envoie l'univers et le joueur au modele
        self.modele.joindrePartie(univers, joueur)
        self.vue.couleurs = couleurs
        ##change l'ecran pour afficher la partie en cours
        self.vue.partieEnCours()
        ##part la loop de controle
        threading.Timer(0.1,self.loopControle).start()
        #self.modele.initMouvement(0,500,350,5)        
     
    def creerUnite(self,type,indexEtoile):
        if self.modele.verifierRessources("unite" , type, indexEtoile):
            toto = self.serveur.creerUnite(indexEtoile, type)
            self.modele.creerUnite(indexEtoile, type)
            self.modele.joueur.unites.append(len(self.modele.univers.tabUnites)-1)
            return "Unite Creee"
        else: 
            return "manque de ressources"  
    def augmenterPopulation (self,etoile):
        if self.modele.verifierRessource('stationSpatiale',3):
           if self.modele.requis(etoile): 
                self.modele.augmenterPopulation(etoile)
                return "Population Augmenter"
           else:
                return "Impossible de faire l'augmentation"
        else:
            return "manque de ressource"
    def augmentePoint(self,structure):
        if self.modele.verifierRessources("technologie",0,0):
            m=self.modele.augmentePoint(structure)
            return "Point de technologie"+m+" augmenter"
        else:
            return "Manque de Ressources"
        
    def construireStructure(self,structure,etoile):
        if self.modele.verifierRessource(structure,2):
            if self.modele.dejaConstruit(structure,etoile):
                toto= self.serveur.construireStructure(etoile,structure)
                self.modele.construireStructure(structure,etoile)
                return 'Structure Construite : '+ structure
            else:
                return 'Structure deja construite sur cette etoile'
        else:
            return 'manque de ressource pour construire '+structure
                        
    ##Demander la liste des changements au serveur
    ##puis la traiter
    def ping(self):
        bin = self.serveur.ping(self.modele.joueur.nom)  #charge seulement les evenements utiles pour le joueur
        if bin <> "rien":
            bin = pickle.loads(bin)
            for i in bin:
                if i[0]=="mvt": ##Lorsqu'un autre joueur initialise un mouvement
                    indexUnite=i[1]
                    x=i[2]
                    y=i[3]
                    z=i[4]
                    self.modele.initMouvement(indexUnite,x,y,z)
                elif i[0]=="nouveauJoueur": ##Lorsqu'un joueur joint la partie
                    newJoueur=i[1]
                    newEtoile=i[2]
                    newUnite=i[3]
                    couleur = i[4]
                    self.vue.couleurs[newJoueur]=couleur
                    self.modele.nouveauJoueur(newJoueur,newEtoile,newUnite)
                    self.vue.afficher()
                elif i[0]=="attaque":##Lorsqu'un autre joueur initialise une attaque
                    attaquant=i[1]
                    defenseur=i[2]
                    self.modele.initAttaque(attaquant,defenseur)
                elif i[0]=="cancelAttaque":##Lorsqu'un joueur en attaque initialise un mouvement
                    attaquant=i[1]
                    self.modele.cancelAttaque(attaquant)
                elif i[0]=="creerUnite":
                    type=i[2]
                    etoile=int(i[1])
                    self.modele.creerUnite(etoile, type)
                elif i[0] == "construireStructure":
                    structure = i[1]
                    etoile = i[2]
                    self.modele.construireStructure(structure,etoile)
                elif i[0]=="shieldDisrupt":##Lorsqu'un joueur utilise un shield Disruptor
                    defenseur=i[1]
                    self.modele.shieldDisrupt(defenseur)
                elif i[0] == "construireStructure":
                    structure = i[1]
                    etoile = i[2]
                    self.modele.construireStructure(structure,etoile)
                elif i[0] == "reparer":
                    indexUniteReparer = i[1]
                    self.modele.initReparer(indexUniteRaparteur, indexUniteReparer)
                elif i[0] == "chat":
                    chat = i[1]
                    joueur = i[2]
                    self.modele.changerTextChat(chat, joueur)
                           
                    
                    
    
    ##Lorsque le joueur initialise un deplacement sur le serveur
    ##puis dans le modele
    def initMouvement(self,indexUnite,x,y,z):
        toto=self.serveur.initMouvement(indexUnite,x,y,z)
        self.modele.initMouvement(indexUnite,x,y,z)
        
    def cancelAttaque(self,index):
        toto=self.serveur.cancelAttaque(index)
        self.modele.cancelAttaque(index)
        
    def checkProprietaire(self, indexUnite):
        return self.modele.checkProprietaire(indexUnite)
    
    def checkProprietaireEtoile(self, indexEtoile):
        return self.modele.checkProprietaireEtoile(indexEtoile)
    
    def bougerUnites(self):
        self.vue.effacer()
        self.modele.bougerUnites()
        self.vue.afficher()
        self.vue.afficherEtoiles()
    
    def initAttaque(self,indexUniteAttaque,indexUniteDefense):
        popo=self.serveur.initAttaque(indexUniteAttaque,indexUniteDefense)
        self.modele.initAttaque(indexUniteAttaque,indexUniteDefense)
        
    def shieldDisrupt(self, indexUniteAttaque, indexUniteDefense):
        distance = self.modele.shieldDisruptDistance(indexUniteAttaque, indexUniteDefense)
        if distance == "ok":
            self.modele.shieldDisrupt(indexUniteDefense)
            bobo = self.serveur.shieldDisrupt(indexUniteAttaque, indexUniteDefense)
            
    def initReparer(self, indexUniteReparateur, indexUniteReparer):
        self.modele.initReparer(indexUniteReparateur, indexUniteReparer)
        lolo = self.serveur.initReparer(indexUniteReparateur, indexUniteReparer)
    
    def augmenterArgent(self):
        self.modele.augmenterArgent()
        
    def attaquer(self):
        self.modele.attaquer()
        
    def reparer(self):
        self.modele.reparer()
        
    def loopControle(self):
        if self.compteur < 7:
            self.compteur+=1
        else:
            self.augmenterArgent()
            self.modele.changerPopulation()
            self.modele.ticBatiments()
            self.compteur=1
            self.ping()
            self.attaquer() ##attaque au 5 tics
            self.reparer()
        self.bougerUnites()
        self.gererGuides()
        self.vue.statJoueur()
        if self.vue.selectionne <> "":
            self.vue.stat()
        elif self.vue.structureSelectionnee <> "":
            self.vue.statStructure()
        elif self.vue.planeteSelectionnee <> "":
            self.vue.statPlanete()
        elif self.vue.etoileSelectionnee <> "":
            self.vue.statEtoile()
        else:
            if self.vue.etoileSelectionnee =="" and self.vue.structureSelectionnee =="" and self.vue.planeteSelectionnee =="":
                self.vue.statTampon()
                
        #########################################
        self.modele.riposte()
        for i in self.getTabUnites():
            i.hpPrePing=i.hp
            i.shieldsPrePing=i.shields
            
        self.vue.root.after(100, self.loopControle)
            
        
        
        
        #threading.Timer(0.1,self.loopControle).start()
    def gererGuides(self):
        fini=[]
        for guide in self.modele.joueur.guidesActifs:
            cible = self.modele.joueur.guidesActifs[guide]
            if self.modele.checkDistance("etoile", cible, guide):
                self.approprierEtoile(guide, cible)
                fini.append(guide)
        for i in fini:
            del self.modele.joueur.guidesActifs[i]
                
    def getTabEtoiles(self):
        return self.modele.univers.tabEtoiles
    def getTabUnites(self):
        return self.modele.univers.tabUnites
#    def deplacerUnite(self, x, y, unite):
#        self.modele.deplacerUnite(x, y, unite)

    def approprierEtoile(self, unite, indexEtoile):
        nick = self.modele.joueur.nom
        if self.modele.checkDistance("etoile", indexEtoile, unite):
            boboche = self.serveur.approprierEtoile(nick, indexEtoile)
            self.modele.approprierEtoile(nick, indexEtoile)
            self.modele.joueur.etoiles.append(indexEtoile)
            self.construireStructure('stationSpatiale',indexEtoile)
        else:
            x = self.modele.univers.tabEtoiles[indexEtoile].x
            y = self.modele.univers.tabEtoiles[indexEtoile].y
            z = self.modele.univers.tabEtoiles[indexEtoile].z
            self.initMouvement(unite, x, y, z)
            self.modele.joueur.guidesActifs[unite]=indexEtoile
        
    def creerBatiment(self, planeteSelectionnee, etoileSelectionnee, typeBatiment):
        message = self.modele.creerBatiment(planeteSelectionnee, etoileSelectionnee, typeBatiment)
        return message
    
    def changerTextChat(self, chat, joueur):
        self.vue.changerTextChat(chat, joueur)
        
    def nouveauTextChat(self, chat):
        self.modele.changerTextChat(chat, self.modele.joueur.nom)
        bobo = self.serveur.changerTextChat(chat, self.modele.joueur.nom)
               
jeu=Controleur()